package com.zws.cucumber.expr;

import com.zws.cucumber.util.colorfullog.ZwsColorfulLogger;
import com.zws.cucumber.util.colorfullog.ZwsPrintTableHelper;
import com.zws.cucumber.var.ZwsVar;
import com.zws.cucumber.var.ZwsVarBlock;
import groovy.lang.Closure;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;

import javax.script.Bindings;
import javax.script.ScriptContext;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * author: zws
 */
public class ZwsExprUtils {

    private static final Logger logger = ZwsColorfulLogger.of(ZwsExprUtils.class);

    public static void pushVarBlockAndFillAttrs(ScriptContext scriptContext) {
        pushVarBlockAndFillAttrs(scriptContext, null);
    }

    public static void pushVarBlockAndFillAttrs(ScriptContext scriptContext, Map<String, Object> toMerge) {
        long now = System.currentTimeMillis();

        ZwsVarBlock block = ZwsVar.pushProcedureBlock();
        block.put("now", now);
        block.put("debug", new DebugGroovyClosure<>(null));
        if (toMerge != null) {
            block.putAll(toMerge);
        }
        scriptContext.setBindings(ZwsVar.newBlockBindings(block), ScriptContext.ENGINE_SCOPE);
//        scriptContext.setAttribute("now", now, ScriptContext.ENGINE_SCOPE);
//        ZwsVar.getVariableMap()
//            .entrySet()
//            .stream()
//            .forEach(entry -> {
//                scriptContext.setAttribute(entry.getKey(), entry.getValue(), ScriptContext.ENGINE_SCOPE);
//            });
//        scriptContext.setAttribute("debug", new DebugGroovyClosure<>(null), ScriptContext.ENGINE_SCOPE);
    }

    public static void printAttributeOfScriptContext(ScriptContext scriptContext) {
        Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
        List<Map<String, Object>> table = bindings.entrySet()
            .stream()
            .filter(en -> !(en.getValue() instanceof Closure))
            .map(en -> {
                Map<String, Object> row = new HashMap<>();
                row.put("Name", en.getKey());
                row.put("Value", en.getValue());
                return row;
            })
            .collect(Collectors.toList());

        ZwsPrintTableHelper.printTable0("Groovy Attributes",
            Pair.of(Arrays.asList("Name", "Value"), table));
    }

    public static class DebugGroovyClosure<V> extends Closure<V> {
        private int counter = 0;
        public DebugGroovyClosure(Object owner) {
            super(owner);
        }
        @Override
        public V call(Object arg) {
            logger.debug("evaluate, debug {}, <b>{}:[</b>{}<b>]</b>", counter++,
                arg == null ? "null" : arg.getClass().getSimpleName(), arg);
            return (V) arg;
        }
    }

}
